﻿using UnityEngine;
using System.Collections;

public enum States
{
	walk,
	idle,
	fall,
	jump,
	blink,
	climbR,
	climbL,
	attack,
	carry,
	carryIdl,
	lever
}

public class playerScript : MonoBehaviour {
	
	public States currentState;
	//public 
	
	AssetManagerScript assets;
	public Sprites mySprite;
	Sprites mySpriteHand;
	SpriteState jumpS, fallS, walkS, idleS, blinkS, climbRS, climbLS, attackS, carryS, carryIdlS, leverS;
	public Renderer myRendeder;
	public Renderer handRend;
	public ParticleSystem myDeathParticle;
	
	private float jumpHeight,gravity,groundDist,sideDist,sideFar;
	private float moveSpeed;
	private float maxVelocity;
	private bool disableControls;
	
	public bool isGrounded = false,isJumping;
	public bool isAlive;
	
	public Vector3 initialPos;
	public float direction = 1;
	Vector3 initialScale;
	Vector3 negativeScale;
	
	public GameManagerScript manager;
	GameObject latestPlatform;
	float playerHalfSize;
	
	//NETWORK VARIABLES
	float targetX;
	float offSetAmount;
	bool stopMovingX;
	int moveToModifier;
	bool isMine;
	float reSyncCounter;
	bool finishClimbing;
	int climbToModifier;
	bool isOnPlatform;
	
	//CLIMBING VARIABLES
	public bool canClimb;
	public bool isClimbing;
	LadderScript latestLadder;
	float climbSpeed;
	
	
	//ITEM VARIABLES
	ItemScript currentItem;
	
	//dying variables
	public Transform latestCheckPoint;
	float lerpCounter;
	float reviveSpeed;
	Vector3 deadPosition;
	
	//push/pull variable
	public bool isCarrying;
	public bool isCarryKey;
	public carryableObject latestObject;
	public bool havePickUpThisTurn;
	public bool isBoxGround;
	
	//Attack variables
	bool isAttacking;
	bool appliedAttack;
	
	//blink variables
	float blinkCounter = 0;
	
	//lever variables
	public bool isPushingLever;
	
	#region MONOS
	void FixedUpdate()
	{
		changeGround();
		
		if(isGrounded)
		{
			//Debug.Log(rigidbody.velocity.x);
			Vector3 tmpVel = rigidbody.velocity;
			tmpVel.y = 0;
			rigidbody.velocity = tmpVel;
		}
		
		if(!isClimbing && !isPushingLever)
		{
			if(!disableControls)
			{
				if(moveToModifier != 0)
					ext_applyMovementCalc(moveToModifier);
				
				//velocity decay
				if(isMine)
				{
					if(getWalkInput() == 0)
						rigidbody.velocity = new Vector3(rigidbody.velocity.x * 0.8f, rigidbody.velocity.y, 0);
					else
						ext_applyMovementCalc(getWalkInput());
				}
			}
			
			if(!isGrounded)
			{
				if(rigidbody.velocity.y < 0)
					changeState(States.fall);
				//Debug.Log(rigidbody.velocity.y);
				if(rigidbody.velocity.y < -8)
				{
					Vector3 tmpVel = rigidbody.velocity;
					tmpVel.y = -8;
					rigidbody.velocity = tmpVel;
				}
				rigidbody.AddForce(new Vector3 (0, -gravity * rigidbody.mass, 0),ForceMode.Acceleration);
			}
		}
		else
		{
			if(climbToModifier != 0)
			{
				Vector3 tmpPos = transform.position;
				tmpPos.y += climbToModifier * climbSpeed;
				transform.position = tmpPos;
			}
		}	
	}
	
	void Awake()
	{
		assets = GameObject.FindGameObjectWithTag("AssetManager").GetComponent<AssetManagerScript>();
	}
	
	// Use this for initialization
	void Start () {
		
		latestCheckPoint = transform;
		playerHalfSize = (transform.localScale.y * GetComponent<CapsuleCollider>().height) / 2;
		//Debug.Log(playerHalfSize);
		jumpHeight = 3.5f;
		groundDist = playerHalfSize * 1.02f;
		initialScale = transform.localScale;
		negativeScale = transform.localScale;
		negativeScale.x *= -1;
		sideFar = 0.2f;
		sideDist = Mathf.Sqrt((groundDist * groundDist) + (sideFar * sideFar));
		gravity = 7;
	
		climbSpeed = 0.05f;
		moveSpeed = 0.6f;
		maxVelocity = 4;
		lerpCounter = 0;
		
		manager = GameObject.FindGameObjectWithTag("SceneManager").GetComponent<GameManagerScript>();
		
		initialPos = transform.position;
	
		mySprite = new Sprites(myRendeder,new Vector2(210,190),0,0);
		mySpriteHand = new Sprites(handRend,new Vector2(210,190),0,0);
		idleS = new SpriteState(3,5,2,false);
		walkS = new SpriteState(11,16,8,false);
		jumpS = new SpriteState(6,6,10,true);
		fallS = new SpriteState(6,6,10,true);
		blinkS = new SpriteState(0,2,2,true);
		climbRS = new SpriteState(9,10,4,false);
		climbLS = new SpriteState(7,8,4,false);
		attackS = new SpriteState(0,1,5,true);
		carryS = new SpriteState(21,26,8,false);
		carryIdlS = new SpriteState(27,29,2,false);
		leverS = new SpriteState(17,20,3,true);
		mySprite.innatePosition[0] = new Vector3(-0.06f,-0.46f,1.0f);
		mySprite.innatePosition[1] = new Vector3(-0.07f,-0.44f,1.0f);
		mySprite.innatePosition[2] = new Vector3(-0.08f,-0.42f,1.0f);
		mySprite.innatePosition[3] = new Vector3(-0.06f,-0.46f,1.0f);
		mySprite.innatePosition[4] = new Vector3(-0.07f,-0.44f,1.0f);
		mySprite.innatePosition[5] = new Vector3(-0.08f,-0.42f,1.0f);
		mySprite.innatePosition[6] = new Vector3(0.25f,-0.27f,1.0f);
		mySprite.innatePosition[7] = new Vector3(0f,0f,2.0f);
		mySprite.innatePosition[8] = new Vector3(0f,0f,2.0f);
		mySprite.innatePosition[9] = new Vector3(0f,0f,2.0f);
		mySprite.innatePosition[10] = new Vector3(0f,0f,2.0f);
		mySprite.innatePosition[11] = new Vector3(0.16f,-0.46f,1.0f);
		mySprite.innatePosition[12] = new Vector3(-0.07f,-0.44f,1.0f);
		mySprite.innatePosition[13] = new Vector3(-0.15f,-0.32f,1.0f);
		mySprite.innatePosition[14] = new Vector3(0.16f,-0.46f,1.0f);
		mySprite.innatePosition[15] = new Vector3(0.38f,-0.32f,1.0f);
		mySprite.innatePosition[16] = new Vector3(0.53f,-0.15f,1.0f);
		
		mySprite.innatePosition[17] = new Vector3(0,0,-7.0f);
		mySprite.innatePosition[18] = new Vector3(0,0,-7.0f);
		mySprite.innatePosition[19] = new Vector3(1,0,-7.0f);
		mySprite.innatePosition[20] = new Vector3(2,0,-7.0f);
		
		mySprite.innatePosition[21] = new Vector3(0.4f,0.1f,1.0f);
		mySprite.innatePosition[22] = new Vector3(0.4f,0.11f,1.0f);
		mySprite.innatePosition[23] = new Vector3(0.4f,0.12f,1.0f);
		mySprite.innatePosition[24] = new Vector3(0.4f,0.11f,1.0f);
		mySprite.innatePosition[25] = new Vector3(0.4f,0.10f,1.0f);
		mySprite.innatePosition[26] = new Vector3(0.4f,0.11f,1.0f);
		mySprite.innatePosition[27] = new Vector3(0.4f,0.11f,1.0f);
		mySprite.innatePosition[28] = new Vector3(0.4f,0.09f,1.0f);
		mySprite.innatePosition[29] = new Vector3(0.4f,0.07f,1.0f);
		changeState(States.idle);
		
		isMine = networkView.isMine;
		
		isAlive = true;
	}
	
	// Update is called once per frame
	void Update () {
		//Debug.Log(rigidbody.velocity.x);
		havePickUpThisTurn = false;
		mySprite.Update();
		mySpriteHand.Update();
		if(!manager.levelCompleted)
		{
			if(!disableControls)
			{
				if(isMine)
					UpdateInput();
				
				if(isPushingLever)
				{
					if(currentState != States.lever)
						changeState(States.lever);
					//Debug.Log(mySprite.active);
					if(!mySprite.active)
					{
						//Debug.Log("AW");
						isPushingLever = false;
						
					}
					//else if(
					//{
						
					//}
				}
				else if(!isCarryKey && isCarrying && isGrounded)
				{
					if(getWalkInput() != 0 || moveToModifier != 0)
					{
						changeState(States.carry);
					}
					else
						changeState(States.carryIdl);
				}
				else if(isClimbing)
				{
					
				}
				else if(!isGrounded)
				{
					if(isJumping)
					{
						isJumping = false;
					}
				}
				else if(isJumping)
				{
					
				}
				else if(isMine && getJumpInput())
				{
					if(isGrounded && !isJumping)
					{
						//playerDie();
						networkView.RPC("Jump",RPCMode.Others,transform.position.x, transform.position.y);
						Jump(transform.position.x, transform.position.y);
					}
				}
				else if(getWalkInput() != 0 || moveToModifier != 0)
				{
					changeState(States.walk);
				}
				else
				{
					blinkCounter += Time.deltaTime;
					if(blinkCounter > 5.0f)
					{
						changeState(States.blink);
						blinkCounter = 0;
					}
					else
					{
						if(currentState != States.blink)
							changeState(States.idle);
						else if(!mySprite.active)
							changeState(States.idle);
					}
				}
			}
			else if(!isAlive)
			{
				lerpCounter += Time.deltaTime * reviveSpeed;
				transform.position = Vector3.Lerp(deadPosition, latestCheckPoint.position,lerpCounter);
				if(lerpCounter >= 1.0f)
				{
					transform.position = latestCheckPoint.position;
					lerpCounter = 0;
					playerRevive();
				}
			}
		}
	}
	#endregion
	
	public void changeState(States state)
	{
		if(currentState == state)
			return;
		currentState = state;
		switch(state)
		{
		case States.idle:
			mySprite.Play(idleS);
			mySpriteHand.Play(idleS);
			break;
		case States.walk:
			mySprite.Play(walkS);
			mySpriteHand.Play(walkS);
			break;
		case States.jump:
			mySprite.Play(jumpS);
			mySpriteHand.Play(jumpS);
			break;
		case States.fall:
			mySprite.Play(fallS);
			mySpriteHand.Play(fallS);
			break;
		case States.blink:
			mySprite.Play(blinkS);
			mySpriteHand.Play(blinkS);
			break;
		case States.climbR:
			mySprite.Play(climbRS);
			mySpriteHand.Play(climbRS);
			break;
		case States.climbL:
			mySprite.Play(climbLS);
			mySpriteHand.Play(climbLS);
			break;
		case States.attack:
			mySprite.Play(attackS);
			mySpriteHand.Play(attackS);
			break;
		case States.carry:
			mySprite.Play(carryS);
			mySpriteHand.Play(carryS);
			break;
		case States.carryIdl:
			mySprite.Play(carryIdlS);
			mySpriteHand.Play(carryIdlS);
			break;
		case States.lever:
			mySprite.Play(leverS);
			mySpriteHand.Play(leverS);
			break;
		default:
			break;
		}
	}
	
	#region REMOTE PROCEDURE CALLS
	
	[RPC]
	public void Jump(float xPos, float yPos)
	{
		transform.position = new Vector3(xPos,yPos, transform.position.z);
		rigidbody.velocity = (new Vector3(rigidbody.velocity.x, CalculateJumpVerticalSpeed(1), rigidbody.velocity.z));
		isJumping = true;
		changeState(States.jump);
	}
	
	[RPC]
	public void moveTo(float velX)
	{
		Vector3 tmpVel = rigidbody.velocity;
		tmpVel.x = velX;
		rigidbody.velocity = tmpVel;
		//float vector = transform.position.x - x;
	
		if(velX > 0)
			moveToModifier = 1;
		else if(velX < 0)
			moveToModifier = -1;
		else
			moveToModifier = 0;
		//targetX = x;
	}
	
	[RPC]
	public void unPressedMove(float x, float velX)
	{
		Vector3 tmpVel = rigidbody.velocity;
		tmpVel.x = velX;
		rigidbody.velocity = tmpVel;
		
		targetX = x;
		tmpVel = transform.position;
		tmpVel.x = x;
		transform.position = tmpVel;
		moveToModifier = 0;
	}
	
	[RPC]
	public void stopX(float x)	
	{
		Vector3 tmpVel = rigidbody.velocity;
		tmpVel.x = 0;
		rigidbody.velocity = tmpVel;
		
		tmpVel = transform.position;
		tmpVel.x = x;
		transform.position = tmpVel;
		
		targetX = tmpVel.x;
		moveToModifier = 0;
	}
	
	[RPC]
	public void reSyncPosY(float y)
	{
		//force sync the Y
		if(transform.position.y != y)
		{
			Vector3 tmpPos = transform.position;
			tmpPos.y = y;
			transform.position = tmpPos;
		}
	}
	
	[RPC]
	public void reSyncPos(float x,float y)
	{
		//force sync the Pos
		Vector3 tmpPos = new Vector3(x,y, transform.position.z);
		transform.position = tmpPos;
	}
	
	[RPC]
	public void letMeFallDown()
	{
		if(isClimbing)
		{
			isClimbing = false;
		}
		else if(isGrounded)
		{
			latestPlatform.GetComponent<PlatformCollision>().letPlayerDown();
			if(transform.parent)
			{
				transform.parent = null;
				updateScales();
				isOnPlatform = false;
			}
			isOnPlatform = false;
		}
	}
	
	//LADDER SPECIFIC
	[RPC]
	public void startClimbing(float posX, bool isLadder)
	{
		Vector3 tmpPos = transform.position;
		tmpPos.x = posX;
		transform.position = tmpPos;
		rigidbody.velocity = Vector3.zero;
		isClimbing = true;
		canClimb = false;
		
		if(isLadder)
			changeState(States.climbL);
		else
			changeState(States.climbR);
	}
	
	[RPC]
	public void climbTo(int posY)
	{
		climbToModifier = posY;
		mySprite.active = true;
	}
	
	[RPC]
	public void endClimbing()
	{
		canClimb = false;
		isClimbing = false;
	}
	
	[RPC]
	public void stopClimbing()
	{
		climbToModifier = 0;
		mySprite.active = false;
	}
	
	[RPC]
	public void updatePlatform(bool isOnPlat)
	{
		isOnPlatform = isOnPlat;
	}
	
	[RPC]
	public void RPC_setAsPartner(int textureIndex)
	{
		followArrowScript tmpAScript = GameObject.FindGameObjectWithTag("ArrowPointer").GetComponent<followArrowScript>();
		tmpAScript.setPlayer(this);
		//tmpAScript.partnerRend = this.myRendeder.transform;
		
		myRendeder.material = (Material)assets.playerMaterials[1];
		myRendeder.material.mainTexture = (Texture)assets.playerTextures[textureIndex];
		myRendeder.material.SetTexture("Displacement",(Texture)assets.playerHndTextures[textureIndex]);
		handRend.material = (Material)assets.playerMaterials[0];
		handRend.material.mainTexture = (Texture)assets.playerHndTextures[textureIndex];
		mySprite = new Sprites(myRendeder,new Vector2(210,190),0,0);
		mySpriteHand = new Sprites(handRend,new Vector2(210,190),0,0);
	}
	
	[RPC]
	public void RPC_die()
	{
		isAlive = false;
		if(latestObject != null)
		{
			if(isCarryKey)
			{
				latestObject.myParent = null;
				latestObject.GetComponent<keyScript>().resetPos();
				latestObject = null;
				isCarrying = false;
				isCarryKey = false;
			}
			else
			{
				latestObject.gameObject.SetActive(false);
			}
			
		}
		myRendeder.gameObject.SetActive(false);
		myDeathParticle.enableEmission = true;
		setDisableControl(true);
		deadPosition = transform.position;
		reviveSpeed = 20 - Vector3.Distance(transform.position,latestCheckPoint.position);
		reviveSpeed /= 10;
		if(reviveSpeed <= 1.0)
			reviveSpeed = 1.0f;
		//renderer.material.sette
	}
	
	[RPC]
	public void RPC_setVelocityX(float amount)
	{
		Vector3 tmpVel = rigidbody.velocity;
		tmpVel.x = amount;
		rigidbody.velocity = tmpVel;
	}
	
	[RPC]
	public void RPC_GetBox(NetworkViewID ID)
	{
		isCarrying = true;
		changeState(States.carry);
		latestObject = NetworkView.Find(ID).GetComponent<carryableObject>();
		latestObject.myParent = this;
		latestObject.collider.enabled = false;
		Vector3 tmpPos = latestObject.transform.position;
		tmpPos.z = transform.position.z;
		latestObject.transform.position = tmpPos;
	}
	
	[RPC]
	public void RPC_GetKey(NetworkViewID ID)
	{
		isCarryKey = true;
		isCarrying = true;
		//changeState(States.carry);
		latestObject = NetworkView.Find(ID).GetComponent<carryableObject>();
		latestObject.myParent = this;
	}
	
	[RPC]
	public void RPC_DropBox()
	{
		if(latestObject.myParent != null)
		{
			Vector3 tmpPos = transform.position;
			tmpPos.y -= 0.75f;
			//if(!havePickUpThisTurn)
			//	havePickUpThisTurn = true;
			//else
			//	return;
			if(isCarryKey)
			{
				if(!isGrounded || isBoxGround)
					return;
				isCarryKey = false;
				tmpPos.y -= 0.30f;
			}
			latestObject.transform.position = tmpPos;
			
			isCarrying = false;
			latestObject.myParent = null;
			
			Vector3 tmpRot = latestObject.transform.eulerAngles;
			tmpRot.z = 180;
			latestObject.transform.eulerAngles = tmpRot;
			
			latestObject = null;
		}
	}
	
	[RPC]
	public void RPC_UnlockDoor()
	{//WARNING MIGHT DELETE THE WRONG OBJECT SOLVE BY PASSING REFERRNCE NETWORKVIEW ID
		isCarrying = false;
		isCarryKey = false;
		Destroy(latestObject.gameObject);
		latestObject = null;
	}
	
	[RPC]
	public void RPC_PushLever(NetworkViewID ID)
	{
		Transform tmpTrans = NetworkView.Find(ID).transform;
		isPushingLever = true;
		rigidbody.velocity = Vector3.zero;
		changeState(States.lever);
		
		Vector3 tmpPos = transform.position;
		tmpPos.x = tmpTrans.position.x;
		transform.position = tmpPos;
		direction = 1;
		transform.localScale = initialScale;
	}
	
	public void nRPC_Bounce(float xPos, float yPos)
	{
		transform.position = new Vector3(xPos,yPos, transform.position.z);
		Vector3 tmpVel = rigidbody.velocity;
		tmpVel.y += CalculateJumpVerticalSpeed(1.7f);
		rigidbody.velocity = tmpVel;
		//rigidbody.velocity.y = (new Vector3(rigidbody.velocity.x, CalculateJumpVerticalSpeed(1), rigidbody.velocity.z));
		isJumping = true;
		changeState(States.jump);
	}
	
	#endregion
	
	#region INPUT FUNCTIONS
	int getWalkInput()
	{
		if(!isMine)
			return 0;
		
		if(Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
			return -1;
		else if(Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
			return 1;
		
		return 0;
	}
	
	int getClimbInput()
	{
		if(!isMine)
			return 0;
		
		if(Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
			return 1;
		else if(Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
			return -1;
		
		return 0;
	}
	
	bool getJumpInput()
	{
		if(Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow))
			return true;
		return false;
	}
	
	bool getAttackInput()
	{
		if(Input.GetMouseButtonDown(1))
			return true;
		return false;
	}
	
	void UpdateInput()
	{
		/*if(!isClimbing && isGrounded)
		{
			if(getAttackInput())
			{
				isAttacking = true;
				appliedAttack = false;
				changeState(States.attack);
				
				Vector3 tmpStart = transform.position;
				tmpStart.x += 0.5f;
				tmpStart.y -= playerHalfSize / 2;
				Vector3 tmpEnd = tmpStart;
				tmpEnd.x += 1.3f;
				
				Debug.DrawLine(tmpStart,tmpEnd);
				RaycastHit[] hit;
				hit = Physics.RaycastAll (transform.position, Vector3.down,groundDist + 0.05f);
				
				rigidbody.velocity = Vector3.zero;
				return;
			}
		}*/
		
		if(getWalkInput() != 0)
		{
			networkView.RPC("moveTo",RPCMode.Others,rigidbody.velocity.x);
			stopMovingX = false;
		}
		else if(rigidbody.velocity.x != 0)
		{
			networkView.RPC("unPressedMove",RPCMode.Others,transform.position.x,rigidbody.velocity.x);
		}
		else
		{
			if(!stopMovingX)
			{
				networkView.RPC("stopX",RPCMode.Others,transform.position.x);
				stopMovingX = true;
			}
		}
		
		if(rigidbody.velocity.y == 0 && !isOnPlatform)	//wait till not moving
		{
			if(reSyncCounter >= 1.0f)
			{
				networkView.RPC("reSyncPosY",RPCMode.Others,transform.position.y);
				reSyncCounter = 0;
			}
			else
				reSyncCounter += Time.deltaTime;
		}
		else if(reSyncCounter != 0)
			reSyncCounter = 0;
		
		if(Input.GetKeyDown(KeyCode.R))
		{
			fallDown();
		}
		  
		if(isCarrying && !havePickUpThisTurn)
		{
			if(Input.GetKeyDown(KeyCode.F))
			{
				//Debug.Log("DROP");
				havePickUpThisTurn = true;
				dropBox();
			}
		}
		
		if(!isClimbing)
		{
			if(canClimb && getClimbInput() != 0)
			{
				//bool isAbove = latestLadder.transform.position.y > transform.position.y ? true : false;
				if(getClimbInput() > 0 && latestLadder.transform.position.y < transform.position.y)
				{;}
				else
				{
					Vector3 tmpPos = transform.position;
					tmpPos.x = latestLadder.transform.position.x;
					transform.position = tmpPos;
					rigidbody.velocity = Vector3.zero;
					isClimbing = true;
					canClimb = false;
					if(latestLadder.isLadder)
						changeState(States.climbL);
					else
						changeState(States.climbR);
					
					networkView.RPC("startClimbing",RPCMode.Others,latestLadder.transform.position.x, latestLadder.isLadder);
				}
				//Debug.Log(dist);
			}
		}
		else
		{
			climbToModifier = getClimbInput();
			if(climbToModifier != 0)
			{
				if(transform.position.y < latestLadder.maxY)
				{	
					mySprite.active = true;
					networkView.RPC("climbTo",RPCMode.Others,climbToModifier);
					finishClimbing = true;
				}
				else 
				{
					if(climbToModifier > 0)
					{
						climbToModifier = 0;
						mySprite.active = false;
						networkView.RPC("stopClimbing",RPCMode.Others);
						finishClimbing = false;
					}
				}
			}
			else if(finishClimbing)
			{	
				mySprite.active = false;
				networkView.RPC("stopClimbing",RPCMode.Others);
				finishClimbing = false;
			}
			else if(getWalkInput() != 0)
			{
				float amount = getWalkInput() * 10;
				Vector3 tmpVel = rigidbody.velocity;
				tmpVel.x += amount;
				rigidbody.velocity = tmpVel;
				networkView.RPC("RPC_setVelocityX",RPCMode.Others,amount);
				
				fallDown();
			}
		}
	}
	
	float CalculateJumpVerticalSpeed (float offSet) {
        return Mathf.Sqrt(2 * jumpHeight * gravity * offSet);
    }
	#endregion
	
	#region COLLISION CASTS
	void changeGround() {
		if(rigidbody.velocity.y > 0.0001f)
		{
			if(transform.parent)
			{
				transform.parent = null;
				updateScales();
				isOnPlatform = false;
			}
			isGrounded = false;
			return;
		}
		
		RaycastHit[] hit;
		//bool hittedGround =false;
		
		//FLOOR RAYS
		//downRay
		hit = Physics.RaycastAll (transform.position, Vector3.down,groundDist + 0.05f);
	    for(int i = 0; i < hit.Length; i++) 
		{
			//tmpHit[i] = hit[i].transform.gameObject;
			if(MyGroundEnter(hit[i].transform))
				return;
	    }
		//Debug.Log(hit.Length);
		
		//rightRay
		hit = Physics.RaycastAll (transform.position, new Vector3(sideFar, -groundDist,0),sideDist + 0.05f);
	    for(int i = 0; i < hit.Length; i++) 
		{
			if(MyGroundEnter(hit[i].transform))
				return;
	    }
		
		//leftRay
		hit = Physics.RaycastAll (transform.position, new Vector3(-sideFar, -groundDist,0),sideDist + 0.05f);
	    for(int i = 0; i < hit.Length; i++) 
		{
			if(MyGroundEnter(hit[i].transform))
				return;
	    }
		
		//if(hittedGround)
		//	return;
		//Debug.Log("Exit");
		isGrounded = false;
		if(transform.parent)
		{
			transform.parent = null;
			updateScales();
			isOnPlatform = false;
		}
	}
	
	bool MyGroundEnter(Transform myGameObject)
	{
		//Debug.Log(myGameObject.name);
		if(myGameObject.tag == "Ground")
		{
			//Debug.Log(myGameObject.name);
			if(hittedGround(myGameObject))
				return true;
		}
		else if(myGameObject.tag == "Platform")
		{
			if(myGameObject.collider.enabled)
			{
				if(hittedGround(myGameObject))
				{
					transform.parent = myGameObject;
					updateScales();
					networkView.RPC("updatePlatform",RPCMode.Others,true);
					isOnPlatform = true;
					return true;
				}
			}
		}
		return false;
	}
	
	bool hittedGround(Transform myTransform)
	{
		float tmpPlayerY = transform.position.y;
		tmpPlayerY -= playerHalfSize;
		float tmpPlatY = myTransform.position.y;
		tmpPlatY += myTransform.localScale.y / 2;
		
		if(tmpPlayerY + 0.15f < tmpPlatY)
		{
			isGrounded = false;
			return isGrounded;
		}
		
		PlatformCollision tmpScript = myTransform.GetComponent<PlatformCollision>();
		if(tmpScript == null && tmpScript.isIgnore)
		{
			return false;
		}
		else if(tmpScript.isHidden)
		{
			tmpScript.GetComponent<hiddenPlatformScript>().isStepping = true;
		}
		
		if(isGrounded)
			return isGrounded;
		
		
		latestPlatform = myTransform.gameObject;
		float offSetHeight = myTransform.localScale.y;
		offSetHeight /= 2;
		offSetHeight += playerHalfSize;
		Vector3 tmpVec;
		tmpVec = transform.position;
		tmpVec.y = myTransform.position.y + offSetHeight;
		transform.position = tmpVec;
		
		isBoxGround = tmpScript.isBox;
		
		tmpVec = rigidbody.velocity;
		tmpVec.y = 0;
		rigidbody.velocity = tmpVec;
		
		//if(tmpScript.isMushroom)
		//{
			//nRPC_Bounce(transform.position.x, transform.position.y);
			//isGrounded = false;
			//return isGrounded;
		//}
		
		isGrounded = true;
		return isGrounded;
	}
	
	public void updateScales()
	{
		initialScale = transform.localScale;
		negativeScale = transform.localScale;
		if(direction == 1)
			negativeScale.x *= -1;
		else
			initialScale.x *= -1;
	}
	
	void OnTriggerEnter(Collider myCol)
	{
		if(myCol.gameObject.tag == "SafetyNet")
		{
			Vector3 tmpVel = rigidbody.velocity;	
			tmpVel.y = -0.5f;
			rigidbody.velocity = tmpVel;
			tmpVel = transform.position;
			tmpVel.y = 12;
			transform.position = tmpVel;
		}
		else if(myCol.gameObject.tag == "Ladder")
		{
			canClimb = true;
		}
	}
	
	public void OnLadderEnter(LadderScript ladder)
	{
		canClimb = true;
		latestLadder = ladder;
	}
	
	public void OnLadderExit(LadderScript ladder)
	{
		//Debug.Log(isClimbing);
			
		if(ladder == latestLadder)	
		{
			//Debug.Log(isClimbing);
			ladder = null;
			canClimb = false;
			isClimbing = false;
			networkView.RPC("endClimbing",RPCMode.Others);
		}
	}
	
	#endregion
	
	public void playerDie()
	{
		networkView.RPC("RPC_die",RPCMode.Others);
		RPC_die();
	}
	
	void fallDown()
	{
		if(isClimbing)
		{
			isClimbing = false;
		}
		else if(isGrounded)
		{
			latestPlatform.GetComponent<PlatformCollision>().letPlayerDown();
			if(transform.parent)
			{
				transform.parent = null;
				updateScales();
			}
		}
		networkView.RPC("letMeFallDown",RPCMode.Others);
	}
	
	public void initLooks(int textureIndex)
	{
		//int otherIndex = (textureIndex + 1) % 2;
		myRendeder.material.mainTexture = (Texture)assets.playerTextures[textureIndex];
		handRend.material.mainTexture = (Texture)assets.playerHndTextures[textureIndex];
		networkView.RPC("RPC_setAsPartner",RPCMode.Others,textureIndex);
	}
	
	public void pickUpItem(ItemScript myItem)
	{
		//changeState(States.idle);
		//setDisableControl(true);
		currentItem = myItem;
		myItem.transform.parent = this.transform;
	}
	
	void ext_applyMovementCalc(float dir)
	{
		if(dir > 0)
		{
			direction = 1;
			transform.localScale = initialScale;
		}
		else 
		{
			direction = -1;
			transform.localScale = negativeScale;
		}			
	
		if(isGrounded)
			dir *= moveSpeed;
		else
			dir *= moveSpeed / 6;
		
		// Calculate the new position based on the above input.
		// If you want to limit the movement, you can use Mathf.Clamp
		// to limit the allowed range of newPos.x or newPos.y.
		Vector3 newPos =  new Vector3(dir, 0.0f, 0.0f);
		//Debug.Log(rigidbody.velocity.x);
		// Move the object.
		rigidbody.AddForce(newPos,ForceMode.VelocityChange);
		//rigidbody.AddForceAtPosition(newPos,Vector3.down);
		
		if(Mathf.Abs(rigidbody.velocity.x) > maxVelocity)
		{
			Vector3 tmpVel;
			tmpVel = rigidbody.velocity;
			if(tmpVel.x > 0)
				tmpVel.x = maxVelocity;
			else
				tmpVel.x = -maxVelocity;
			rigidbody.velocity = tmpVel;
		}
	}
	
	
	public void boxHold(boxScript myBox)
	{
		RPC_GetBox(myBox.networkView.viewID);
		networkView.RPC("RPC_GetBox",RPCMode.Others,myBox.networkView.viewID);
	}
	
	public void dropBox()
	{
		networkView.RPC("RPC_DropBox",RPCMode.Others);
		RPC_DropBox();
	}
	
	public void keyHold(keyScript myBox)
	{
		RPC_GetKey(myBox.networkView.viewID);
		networkView.RPC("RPC_GetKey",RPCMode.Others,myBox.networkView.viewID);
	}
	
	public void unlockDoor()
	{
		RPC_UnlockDoor();
		networkView.RPC("RPC_UnlockDoor",RPCMode.Others);
	}
	
	public void pushLever(leverScript myLever)
	{
		RPC_PushLever(myLever.networkView.viewID);
		networkView.RPC("RPC_PushLever",RPCMode.Others,myLever.networkView.viewID);
	}
	
#region getterSetters
	
	public void setDisableControl(bool isDisable)
	{
		disableControls = isDisable;
		if(isDisable)
		{
			rigidbody.velocity = Vector3.zero;
			networkView.RPC("stopX",RPCMode.Others,transform.position.x);
		}
	}
	
	public bool getIsDisabledControls()
	{
		return disableControls;
	}
	
#endregion
	
	public void playerRevive()
	{
		if(latestObject != null)
		{
			latestObject.gameObject.SetActive(true);
		}
		isAlive = true;
		myRendeder.gameObject.SetActive(true);
		myDeathParticle.enableEmission = false;
		disableControls = false;
	}
	
	public void setCheckPoint(Transform myCheckPoint)
	{
		latestCheckPoint = myCheckPoint;
	}
	
	public Vector3 getSpriteInatePos()
	{
		Vector3 tmpPos = mySprite.getInnatePosition();
		tmpPos.x *= direction;
		return tmpPos;
	}
	
	/*
	public void reset()
	{
		isAlive = true;
		gameObject.SetActive(true);
		//torchAmount = torchMax;
		rigidbody.velocity = Vector3.zero;
		transform.position = initialPos;
		transform.parent = null;
		updateScales();
	}
	
	public bool walkToPosition(float xPos)
	{
		changeState(States.walk);

		if(Mathf.Abs(transform.position.x - xPos) > 0.1f)
		{
			float posX;
			
			//if(Input.GetAxis("Horizontal") > 0)
			posX = xPos - transform.position.x;
		
			if(posX > 0)
			{
				posX = 1;
				direction = 1;
				transform.localScale = initialScale;
			}
			else 
			{
				posX = -1;
				direction = -1;
				transform.localScale = negativeScale;
			}			
		
			//if(isGrounded)
				posX *= moveSpeed * Time.deltaTime;
			//else
			//	posX *= moveSpeed * Time.deltaTime / 6;
			
			// Calculate the new position based on the above input.
			// If you want to limit the movement, you can use Mathf.Clamp
			// to limit the allowed range of newPos.x or newPos.y.
			Vector3 newPos =  new Vector3(posX, 0.0f, 0.0f);
			//Debug.Log(rigidbody.velocity.x);
			// Move the object.
			rigidbody.AddForce(newPos,ForceMode.VelocityChange);
			//rigidbody.AddForceAtPosition(newPos,Vector3.down);
			
			//limit max velocity
			if(Mathf.Abs(rigidbody.velocity.x) > maxVelocity)
			{
				Vector3 tmpVel;
				tmpVel = rigidbody.velocity;
				if(tmpVel.x > 0)
					tmpVel.x = maxVelocity;
				else
					tmpVel.x = -maxVelocity;
				rigidbody.velocity = tmpVel;
			}
			return true;
		}
		rigidbody.velocity = Vector3.zero;
		return false;
	}
	*/
}
